package biback.domain.product

import biback.domain.customer.{CustomerStatus, IdValidationType}
import biback.domain.product.ProductParam._

trait DepositProduct extends ProductPolicy {
  this: BaseProduct =>
  type DepositPreSetter = TrnChannelSetter with InvokerSetter
  def depositPre(param: ProductParam, inputs: DepositPreSetter): ErrOrNone =
    param.cashingX(inputs)

  type WithdrawPreSetter = TrnChannelSetter with InvokerSetter
  def withdrawPre(param: ProductParam, inputs: WithdrawPreSetter): ErrOrNone =
    param.cashingX(inputs)
}

trait CurrentDepositProduct extends DepositProduct {
  this: BaseProduct =>
  type OpenSetter = CustomerStatusSetter with MinMaxValuesSetter
  def open(param: ProductParam, inputs: OpenSetter): ErrOrNone =
    for {
      _ <- param.customerStatusX(inputs, CustomerStatus.Normal)
      _ <- param.minMaxLimitsX(inputs)
    } yield ()
}

trait CurrentDeposit1stProduct extends CurrentDepositProduct {
  this: BaseProduct =>
  type OpenPreSetter = OpenChannelSetter with OpenCurrencySetter with OpenBranchSetter with CertSetter with IdValidatedSetter
  def openPre(param: ProductParam, inputs: OpenPreSetter): ErrOrNone =
    for {
      _ <- param.preOpenBaseX(inputs)
      _ <- param.certCheckX(inputs)
      _ <- param.idValidatedX(inputs)
    } yield ()

  type DepositSetter = MinMaxValuesSetter
  def deposit(param: ProductParam, inputs: DepositSetter): ErrOrNone =
    param.minMaxLimitsX(inputs)

  type WithdrawSetter = DepositSetter
  def withdraw(param: ProductParam, inputs: WithdrawSetter): ErrOrNone =
    param.minMaxLimitsX(inputs)
}

trait CurrentDeposit2ndProduct extends CurrentDepositProduct {
  this: BaseProduct =>
  type OpenPreSetter = OpenChannelSetter with OpenCurrencySetter with OpenBranchSetter
  def openPre(param: ProductParam, inputs: OpenPreSetter): ErrOrNone =
    param.preOpenBaseX(inputs)

  type DepositSetter = MinMaxValuesSetter with IdValidatedSetter
  def deposit(param: ProductParam, inputs: DepositSetter): ErrOrNone =
    for {
      _ <- param.minMaxLimitsX(inputs)
      _ <- param.idValidatedCheck(inputs.idValidated, IdValidationType.CounterValidated)
    } yield ()

  type WithdrawSetter = DepositSetter
  def withdraw(param: ProductParam, inputs: WithdrawSetter): ErrOrNone =
    deposit(param, inputs)
}

trait CurrentDeposit3rdProduct extends CurrentDepositProduct {
  this: BaseProduct =>
}

trait FixedDepositProduct extends DepositProduct {
  this: BaseProduct =>
}
